#pragma once

#include <cmath>
#include <cstring>

#include "Common.h"

#include "vec2f.h"
#include "vec3f.h"
#include "vec4f.h"

namespace davmath { class mat4f; }
using namespace davmath;


/* * * * * * * * * *
 * mat4f
 * Author:	David Ogle
 * Date:	26/03/2012
 * 4x4 array of float values
 * Column major order
 * * * * * * * * * */

class davmath::mat4f
{
public:

	// Data union
	// Position vector	- fourth column - values 12, 13, 14
	// Scaling vector	- diagonal		- values 1, 5, 10
	union {
		float i[16];
		struct { float	aa, ab, ac, ad,
						ba, bb, bc, bd,
						ca, cb, cc, cd,
						da, db, dc, dd; };
	};



	// Constructor
	mat4f(void)	{ toIdentity(); }
	mat4f(float elements[16]) { memcpy(this->i, elements, 16 * sizeof(float)); }
	// Destructor
	~mat4f(void) { };



	// Static special matrix creation functions
	static mat4f	rotation		(float degrees, const vec3f &axis);
	static mat4f	scale			(const vec3f &axis);
	static mat4f	translation		(const vec3f &translation);
	static mat4f	perspective		(float znear, float zfar, float aspect, float fov);
	static mat4f	orthographic	(float znear, float zfar, float right, float left, float top, float bottom);
	static mat4f	buildViewMatrix	(const vec3f &from, const vec3f &lookingAt, const vec3f up = vec3f(0, 1, 0));



	// Matrix functions
	void	toZero();
	void	toIdentity();

	vec3f	getPositionVector() const;
	void	setPositionVector(const vec3f &p);

	vec3f	getScalingVector() const;
	void	setScalingVector(const vec3f &s);



	// Matrix operators
	inline mat4f operator*(const mat4f &a) const;
	inline vec3f operator*(const vec3f &v) const;
	inline vec4f operator*(const vec4f &v) const;


};

